home *** CD-ROM | disk | FTP | other *** search
- /*
- StringBounds.c
-
- void StrBounds(char *str,Rect *bounds,long *count);
- void StringBounds(const unsigned char *string,Rect *bounds,long *count);
- StrBounds accepts a C string. StringBounds accepts a pascal string.
- Both routines count--and compute the minimum bounding rectangle for--all the pixels that
- would be set black by calling DrawString with the given string with the
- current port's font, size, and style. Coordinates in the *bounds rect are
- relative to the current pen position. If no pixels would be set then *bounds is
- set to the empty rect (0,0,0,0). The current port is left untouched.
-
- The measurements are based on a full rendering of the string in a private
- GWorld, without any clipping.
-
- The bounds and count arguments are optional; they may be replaced by NULL.
-
- void CharBounds(char a,Rect *bounds,long *count);
- Creates a one-char string and calls StringBounds().
-
- NOTES
-
- bounds->right need not exactly equal the value returned by StringWidth(s),
- because StringWidth returns the displacement of the pen position, and some (e.g.
- italic) characters extend beyond that, while others (e.g. comma) extend less
- far. Similarly, bounds->left need not always be zero.
-
- By QuickDraw's convention, each pixel is considered to lie below and to the
- right of the point that is used to address it. The bounding rectangle for a
- pixel at x,y, is SetRect(&r,x,y,x+1,y+1).
-
- The code assumes ForeColor is black and that TextMode is srcOr, which are the
- default settings for the GWorld that we create.
-
- HISTORY:
- 1/17/94 dgp wrote it, based on discussion with Bart Farell and Manoj Gunwani.
- 2/22/94 dgp added count argument, and made both bounds and count optional.
- 2/27/94 dgp since this routine is typically called repeatedly I save time
- (0.2 s per call) by only allocating the GWorld once, and never
- freeing it. It is reused on subsequent calls, resized appropriately
- if necessary.
- 9/5/94 dgp removed assumption in printf's that int==short.
- 11/2/94 dgp discovered that the clip rect may be nonsense after calling
- UpdateGWorld, so I set it equal to the portRect.
- */
- #include "VideoToolbox.h"
- #include <assert.h>
- #define SHOW_BITMAPS 0 // for debugging
-
- void CharBounds(char a,Rect *boundsPtr,long *countPtr)
- {
- unsigned char string[]="\pA";
-
- string[1]=a;
- StringBounds(string,boundsPtr,countPtr);
- }
-
- void StrBounds(char *s,Rect *boundsPtr,long *countPtr)
- {
- StringBounds(c2pstr(s),boundsPtr,countPtr);
- p2cstr((unsigned char *)s);
- }
-
- void StringBounds(const unsigned char *s,Rect *boundsPtr,long *countPtr)
- {
- static GWorldPtr our=NULL;
- GWorldPtr old;
- GDHandle oldDevice;
- FontInfo f;
- Rect r;
- register unsigned long *pix;
- register int x,y;
- register long count=0;
- int n;
- int error;
- Rect bounds;
- char string[40];
-
- assert(StackSpace()>4000);
- GetFontInfo(&f);
- SetRect(&r,0,-f.ascent,StringWidth(s),f.descent); // nominal size
- InsetRect(&r,-(f.widMax+2),-(f.leading+2)); // add margin
-
- // draw string into a new GWorld
- if(our!=NULL){
- DisposeGWorld(our);
- our=NULL;
- }
- if(our==NULL){
- error=NewGWorld(&our,1,&r,NULL,NULL,keepLocal|useTempMem);
- if(error)error=NewGWorld(&our,1,&r,NULL,NULL,keepLocal);
- }else{
- error=UpdateGWorld(&our,1,&r,NULL,NULL,clipPix);
- assert(EqualRect(&r,&our->portRect));
- assert((**our->clipRgn).rgnSize==10);
- (**our->clipRgn).rgnBBox=our->portRect;
- }
- if(error)PrintfExit("StringBounds: NewGWorld/UpdateGWorld error %d.\n",error);
- GetGWorld(&old,&oldDevice);
- SetGWorld(our,NULL);
- TextFace(old->txFace);
- TextFont(old->txFont);
- TextSize(old->txSize);
- EraseRect(&our->portRect);
- MoveTo(0,0);
- DrawString(s);
- SetGWorld(old,oldDevice);
- if(SHOW_BITMAPS){
- PrintfGWorld(our);
- gets(string);
- }
-
- // measure the bounding box, and count the black pixels
- r=our->portRect;
- SetRect(&bounds,r.right,r.bottom,r.left,r.top);
- n=r.right-r.left;
- pix=(unsigned long *)malloc(n*sizeof(*pix));
- if(pix==NULL)PrintfExit("%s line %d: Couldn't allocate %ld bytes.\n"
- ,__FILE__,__LINE__,n*sizeof(long));
- SetGWorld(our,NULL);
- OffsetRect(&bounds,-r.left,-r.top);
- for(y=0;y<r.bottom-r.top;y++){
- GetPixelsQuickly(r.left,r.top+y,pix,n);
- for(x=n-1;x>=0;x--)if(pix[x]!=0){
- count++;
- if(x<bounds.left)bounds.left=x;
- if(x>=bounds.right)bounds.right=x+1;
- if(y<bounds.top)bounds.top=y;
- if(y>=bounds.bottom)bounds.bottom=y+1;
- }
- }
- OffsetRect(&bounds,r.left,r.top);
- if(SHOW_BITMAPS){
- InvertRect(&bounds);
- PrintfGWorld(our);
- gets(string);
- }
- SetGWorld(old,oldDevice);
- if(EmptyRect(&bounds))SetRect(&bounds,0,0,0,0);
- free(pix);
- // DisposeGWorld(our);
- if(boundsPtr!=NULL)*boundsPtr=bounds;
- if(countPtr!=NULL)*countPtr=count;
- }
-